#include "editwidget.h"
#include "common.h"
#include <stationview.h>
#include <QTime>
#include <QUuid>
#include <QMenu>
#include <QAction>
#include <QDebug>

#include "structurewidget.h"

EditWidget::EditWidget(QString name, QSize size, QWidget *parent)
    : QWidget(parent)
    , mFileName(name)
    , mCopyPos(QPoint(0, 0))
{
   setWindowFlags(Qt::FramelessWindowHint);
   setFocusPolicy(Qt::StrongFocus);
   setMouseTracking(true);
   setFixedSize(size);
   m_width = size.width();
   m_height = size.height();
   mObjectVector.clear();

   m_topLeft = QPoint(0, 0);
   m_rigntBotttom = QPoint(0, 0);

   m_max_single_num = 0;
}

EditWidget::~EditWidget()
{
    ClearVector();
}

//只清除主线路的object
void EditWidget::ClearMainWayVector()
{
    for (auto it = mObjectVector.begin(); it != mObjectVector.end();)
    {
        ViewObjectInfo *info = (ViewObjectInfo *)*it;
        //点线名，预到站时间都会自动重新加载所有都删了，手动拖上去的单独控件不需要删
        if (info->object->GetObjectParam()->GetObjectName() == "StationView" ||
            info->object->GetObjectParam()->GetObjectName() == "LineView"    ||
            info->object->GetObjectParam()->GetObjectName() == "PointView"   ||
            info->object->GetObjectParam()->GetObjectName() == "EtaView")
        {
            if (info->object) {
                info->object->hide();
                delete info->object;
                info->object = NULL;
            }
            delete info;
            info = NULL;
            it = mObjectVector.erase(it);
        }
        else
        {
            it++;
        }
    }
}

void EditWidget::ClearVector()
{
    foreach (ViewObjectInfo *info, mObjectVector)
    {
        if (info)
        {
            if (info->object) {
                info->object->hide();
                delete info->object;
                info->object = NULL;
            }
            delete info;
            info = NULL;
        }
    }
    mObjectVector.clear();
}

//void EditWidget::createActions()
//{
//    //创建菜单、菜单项
//    right_menu = new QMenu(this);
//    action_paste = new QAction(QObject::tr("paste") , this);
//    if (mCopyPos == QPoint(0, 0))

//    //连接信号与槽
//    connect(action_paste, &QAction::triggered, this, &EditWidget::Paste);
//}

//void EditWidget::contextMenuEvent(QContextMenuEvent *event)
//{
//    //清除原有菜单
//    right_menu->clear();
//    right_menu->addAction(action_paste);

//    //菜单出现的位置为当前鼠标的位置
//    right_menu->exec(QCursor::pos());
//    event->accept();
//}

void EditWidget::show_component()
{
    LOG_QDEBUG << "show_component";
    QList<int> index_list;
    foreach (ViewObjectInfo *info, mObjectVector)
    {
        if (!index_list.contains(info->object->GetObjectParam()->GetIndex()))
            index_list.append(info->object->GetObjectParam()->GetIndex());
    }

    std::sort(index_list.begin(), index_list.end());
    foreach (int index, index_list)
    {
        foreach (ViewObjectInfo *info, mObjectVector)
        {
            if (info->object->GetObjectParam()->GetIndex() == index)
            {
                info->object->setParent(this);
                info->object->SetFilename(mFileName);
                info->object->ShowObject();
            }
        }
    }
    foreach (ViewObjectInfo *info, mObjectVector)
        info->object->StartHqv();
}

void EditWidget::Paste()
{
    if (mCopyPos == QPoint(0, 0))
        return;

    if (mCopyID == "")
        return;

    ViewObjectInfo *old_info = NULL;

    for (int i = 0; i < mObjectVector.size(); i++)
    {
        if (mObjectVector[i]->object->GetObjectParam()->GetRandom() == mCopyID)
        {
            old_info = mObjectVector[i];
            break;
        }
    }

    if (!old_info)
        return;

    CopyData(old_info);
    if (!mClipboard)
        return;

    mClipboard->object->GetObjectParam()->SetPos(mCopyPos);
    mClipboard->object->setParent(this);
    mClipboard->object->ShowObject();
    mClipboard->object->StartHqv();

    connect(mClipboard->object, &ViewObject::sgl_viewobject_select_to_editwidget, this, &EditWidget::slt_find_changed_viewobject);
    connect(mClipboard->object, &ViewObject::sgl_viewobject_update_to_editwidget, this, &EditWidget::slt_update_to_attribute);
    connect(mClipboard->object, &ViewObject::signalSelect, this, &EditWidget::ctrl_select);
    connect(mClipboard->object, &ViewObject::signalDelete, this, &EditWidget::sltDeleteObject);
    connect(mClipboard->object, &ViewObject::signalCopy,   this, &EditWidget::sltCopyObjectData);

    mObjectVector.push_back(mClipboard);

    emit signalCopy(mFileName, mClipboard->object->GetObjectParam()->GetObjectName(), mClipboard->object->GetObjectParam()->GetRandom());

    mClipboard = NULL;
    mCopyPos = QPoint(0, 0);
    mCopyID = "";
}

void EditWidget::mousePressEvent(QMouseEvent *event)
{
    if (event->button() == Qt::RightButton)
    {
        if (mCopyID != "")
        {
           mCopyPos = event->pos();
        }
    }
    else if (event->button() == Qt::LeftButton)
    {
        m_topLeft = event->pos();
    }
}

void EditWidget::mouseReleaseEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton)
    {
        if (m_topLeft != QPoint(0, 0))
        {
            m_rigntBotttom = event->pos();
            select_object_by_rect();
            m_topLeft = QPoint(0, 0);
            m_rigntBotttom = QPoint(0, 0);
        }
    }
}

void EditWidget::keyPressEvent(QKeyEvent *event)
{
    if ((event->modifiers() == Qt::ControlModifier) && (event->key() == Qt::Key_V))//粘贴
    {
        LOG_QDEBUG<<"paste";
        Paste();
    }
    else if (event->modifiers() == Qt::ControlModifier)
    {
        LOG_QDEBUG<<event->modifiers();
    }
    else if (event->key() == Qt::Key_Up)
    {
        foreach(ViewObjectInfo *info, mObjectVector)
        {
            if (info->object->GetSelect())
            {
               info->object->Up();
            }
        }
    }
    else if (event->key() == Qt::Key_Down)
    {
        foreach(ViewObjectInfo *info, mObjectVector)
        {
            if (info->object->GetSelect())
            {
               info->object->Down();
            }
        }
    }
    else if (event->key() == Qt::Key_Right)
    {
        foreach(ViewObjectInfo *info, mObjectVector)
        {
            if (info->object->GetSelect())
            {
               info->object->Right();
            }
        }
    }
    else if (event->key() == Qt::Key_Left)
    {
        foreach(ViewObjectInfo *info, mObjectVector)
        {
            if (info->object->GetSelect())
            {
               info->object->Left();
            }
        }
    }
}

void EditWidget::select_object_by_rect()
{
    QRect rect(m_topLeft, m_rigntBotttom);
    foreach(ViewObjectInfo *info, mObjectVector)
    {
        if (rect.contains(info->object->GetObjectParam()->GetPos()) ||
            rect.contains(info->object->GetObjectParam()->GetPos() + QPoint(info->object->GetObjectParam()->GetX(), info->object->GetObjectParam()->GetY())))
        {
           info->object->Select();
        }
    }
}

//拖拽生成控件
QString  EditWidget::generate_interface(QString &file_name, ObjectInfo param, QPoint pos)
{
    file_name = mFileName;
    if (param.object_name == "")
       return "";

    int type = 0;
    for (int i = 0; i < myapp::object_num; i++ )
    {
        if ( ZERO == s_object[i].object_name.compare(param.object_name))
        {
            type = QMetaType::type(s_object[i].object_register_name.toLatin1());
            if (type == 0)
            {
               return STR_EMPTY;
            }
            break;
        }
    }

    ParamObject object_param;
    object_param.SetWidth(param.width);
    object_param.SetHeight(param.height);
    object_param.SetObjectName(param.object_name);
    object_param.SetName(param.object_name.toLower().left(param.object_name.size() - 4));
    object_param.SetRandom(myapp::getRandomString());
    object_param.SetPos(pos);

    ViewObjectInfo *info = new ViewObjectInfo;

    info->object = static_cast<ViewObject*>(QMetaType::metaObjectForType(type)->newInstance());

    if (NULL != info->object)
    {
        info->object->SetObjectParam(object_param);
        info->object->setParent(this);
        info->object->SetFilename(mFileName);
        info->object->ShowObject();//must show now
        info->object->StartHqv();//保证Hqv最后显示

        connect(info->object, &ViewObject::sgl_viewobject_select_to_editwidget, this, &EditWidget::slt_find_changed_viewobject);
        connect(info->object, &ViewObject::sgl_viewobject_update_to_editwidget, this, &EditWidget::slt_update_to_attribute);
        connect(info->object, &ViewObject::signalSelect, this, &EditWidget::ctrl_select);
        connect(info->object, &ViewObject::signalDelete, this, &EditWidget::sltDeleteObject);
        connect(info->object, &ViewObject::signalCopy,   this, &EditWidget::sltCopyObjectData);

        mObjectVector.push_back(info);

        return info->object->GetObjectParam()->GetRandom();
    }
    return  STR_EMPTY;
}

QString EditWidget::CopyArriveFromStationOne(ViewObjectInfo *updata)
{
    ViewObjectInfo *except_1 = new ViewObjectInfo;
    ParamObject *paramobject_1 = updata->object->GetObjectParam();
    int type = 0;
    for (int i = 0; i < myapp::object_num; i++)
    {
        if ( ZERO == s_object[i].object_name.compare(paramobject_1->GetObjectName()))
        {
            type = QMetaType::type(s_object[i].object_register_name.toLatin1());
            break;
        }
    }
    if (type == 0)
    {
        delete except_1;
        return STR_EMPTY;
    }
    except_1->object = static_cast<ViewObject*>(QMetaType::metaObjectForType(type)->newInstance());

    ParamObject object_param;
    object_param.SetIndex(paramobject_1->GetIndex());
    object_param.SetPos(paramobject_1->GetPos());
    object_param.SetWidth(paramobject_1->GetWidth());
    object_param.SetHeight(paramobject_1->GetHeight());
    object_param.SetObjectName(paramobject_1->GetObjectName());
    object_param.SetName(paramobject_1->GetName());
    object_param.SetRandom(myapp::getRandomString());

    if (NULL != except_1->object)
    {
        except_1->object->setParent(this);
        if (paramobject_1->GetObjectName() == "SingleView")
        {
            CopyOneAttribute("normal", updata, except_1);
            object_param.SetName(updata->object->GetObjectParam()->GetName());
        }
        if (paramobject_1->GetObjectName() == "TimeView")
        {
            CopyOneAttribute("timeformat", updata, except_1);
            CopyOneAttribute("font-size", updata, except_1);
        }
        except_1->object->SetObjectParam(object_param);

        connect(except_1->object, &ViewObject::sgl_viewobject_select_to_editwidget, this, &EditWidget::slt_find_changed_viewobject);
        connect(except_1->object, &ViewObject::sgl_viewobject_update_to_editwidget, this, &EditWidget::slt_update_to_attribute);
        connect(except_1->object, &ViewObject::signalSelect, this, &EditWidget::ctrl_select);
        connect(except_1->object, &ViewObject::signalDelete, this, &EditWidget::sltDeleteObject);
        connect(except_1->object, &ViewObject::signalCopy,   this, &EditWidget::sltCopyObjectData);

        mObjectVector.push_back(except_1);

        return except_1->object->GetObjectParam()->GetRandom();
    }

    return STR_EMPTY;
}

void EditWidget::CopyOneAttribute(const std::string &attribute_name, ViewObjectInfo *from, ViewObjectInfo *to)
{
    from->object->GetAttribute(from->attribute);
    bool res;
    JSONCPP_STRING errs;
    Json::Value value;
    Json::CharReaderBuilder readerBuilder;
    std::unique_ptr<Json::CharReader> const jsonReader(readerBuilder.newCharReader());
    res = jsonReader->parse(from->attribute.c_str(), from->attribute.c_str() + from->attribute.length(), &value, &errs);
    if (CheckJsonValueType(value, attribute_name, Json::stringValue))
    {
        Json::Value base;
        Json::StreamWriterBuilder writerBuilder;
        std::ostringstream os;
        base[attribute_name] = value[attribute_name].asString();
        std::unique_ptr<Json::StreamWriter> jsonWriter(writerBuilder.newStreamWriter());
        jsonWriter->write(base, &os);
        to->object->Update(os.str());
    }
}

QString EditWidget::updata2downdata(ViewObjectInfo *updata)
{
     ViewObjectInfo *down_info = new ViewObjectInfo;
     ParamObject *up_paramobject = updata->object->GetObjectParam();
     int type = 0;
     for (int i = 0; i < myapp::object_num; i++)
     {
         if ( ZERO == s_object[i].object_name.compare(up_paramobject->GetObjectName()))
         {
             type = QMetaType::type(s_object[i].object_register_name.toLatin1());
             break;
         }
     }

     if (type == 0)
     {
         delete down_info;
         return STR_EMPTY;
     }

     down_info->object = static_cast<ViewObject*>(QMetaType::metaObjectForType(type)->newInstance());

     int station_num = myapp::mDynamicMapParam->m_station_total;

     ParamObject object_param;
     object_param.SetIndex(up_paramobject->GetIndex());

     //如果是上下行替换全线路或者区间线路， 奇上偶下或者奇下偶上，站点个数是偶数个，则需要将y轴按照中轴线对称
     QPoint pos = up_paramobject->GetPos();
     if (up_paramobject->GetObjectName() == "StationView")
     {
         QStringList list = mFileName.split("_");
         QString ui_type = list.at(ParamType);
         if (ZERO == ui_type.compare(AllFlag) && (myapp::mDynamicMapParam->m_interval_staggered == Odd_Up ||
                                                  myapp::mDynamicMapParam->m_interval_staggered == Even_Up))
         {
             qDebug() << myapp::mDynamicMapParam->mLineInfoVector.length();
             if (station_num%2 == 0 && myapp::mDynamicMapParam->mLineInfoVector.length() == 1)
                 pos.setY(myapp::mDynamicMapParam->mLineInfoVector.first().begin_y*2-pos.y());
         }
     }
     object_param.SetPos(pos);
     /***************************************************************************************/

     object_param.SetWidth(up_paramobject->GetWidth());
     object_param.SetHeight(up_paramobject->GetHeight());
     object_param.SetObjectName(up_paramobject->GetObjectName());
     object_param.SetRandom(myapp::getRandomString());

     //自动生成控件：LineView, PointView, StationView EtaView
     if (up_paramobject->GetStId() != 0)
     {
         myapp::mDynamicMapParam->mLineInfoVector.size();
         int stId = station_num - up_paramobject->GetStId() + 1;
         object_param.SetStId(stId);
         object_param.SetShowLeft(up_paramobject->GetShowLeft());
         object_param.SetName(up_paramobject->GetObjectName().toLower().left(up_paramobject->GetObjectName().size() - 4) +
                                                QString::number(object_param.GetStId()));
     } else
     {
         object_param.SetName(up_paramobject->GetObjectName().toLower().left(up_paramobject->GetObjectName().size() - 4));
     }

     if (NULL != down_info->object)
     {
         down_info->object->setParent(this);
         if (up_paramobject->GetObjectName() == "SingleView")
         {
             CopyOneAttribute("normal", updata, down_info);
             object_param.SetName(updata->object->GetObjectParam()->GetName());
         }
         if (up_paramobject->GetObjectName() == "TimeView")
         {
             CopyOneAttribute("timeformat", updata, down_info);
             CopyOneAttribute("style", updata, down_info);
         }
         down_info->object->SetObjectParam(object_param);

         connect(down_info->object, &ViewObject::sgl_viewobject_select_to_editwidget, this, &EditWidget::slt_find_changed_viewobject);
         connect(down_info->object, &ViewObject::sgl_viewobject_update_to_editwidget, this, &EditWidget::slt_update_to_attribute);
         connect(down_info->object, &ViewObject::signalSelect, this, &EditWidget::ctrl_select);
         connect(down_info->object, &ViewObject::signalDelete, this, &EditWidget::sltDeleteObject);
         connect(down_info->object, &ViewObject::signalCopy,   this, &EditWidget::sltCopyObjectData);

         mObjectVector.push_back(down_info);

         return down_info->object->GetObjectParam()->GetRandom();
     } else {
         delete down_info;
         down_info = NULL;
     }

     return STR_EMPTY;
}

QString EditWidget::original2mirror(ViewObjectInfo *originaldata, QString nonmirror_name)
{
    ViewObjectInfo *mirror_info = new ViewObjectInfo;
    ParamObject *original_paramobject = originaldata->object->GetObjectParam();
    int type = 0;
    for (int i = 0; i < myapp::object_num; i++ )
    {
        if ( ZERO == s_object[i].object_name.compare(original_paramobject->GetObjectName()))
        {
            type = QMetaType::type(s_object[i].object_register_name.toLatin1());
            break;
        }
    }

    if (type == 0)
    {
        delete mirror_info;
        return STR_EMPTY;
    }

    mirror_info->object = static_cast<ViewObject*>(QMetaType::metaObjectForType(type)->newInstance());

    ParamObject object_param;
    object_param.SetIndex(original_paramobject->GetIndex());
    object_param.SetWidth(original_paramobject->GetWidth());
    object_param.SetHeight(original_paramobject->GetHeight());
    object_param.SetObjectName(original_paramobject->GetObjectName());
    object_param.SetRandom(myapp::getRandomString());
    object_param.SetStId(original_paramobject->GetStId());

    //自动生成控件：LineView, PointView, StationView EtaView
    if (original_paramobject->GetStId() != 0)
    {
        int mirror_width = 0;
        //自动生成控件按照最长线段中轴线进行对称
        if (nonmirror_name.contains("all"))
        {
            int begin_to_end = 0;
            int all_name_offset = 0;
            if (myapp::mDynamicMapParam->mLineInfoVector.size() != 0)
            {
                for (int i = 0; i < myapp::mDynamicMapParam->mLineInfoVector.size(); i++)
                {
                    if (begin_to_end < myapp::mDynamicMapParam->mLineInfoVector[i].end_x - myapp::mDynamicMapParam->mLineInfoVector[i].begin_x)
                    {
                        all_name_offset = myapp::mDynamicMapParam->mLineInfoVector[i].name_offset.x();
                        begin_to_end = myapp::mDynamicMapParam->mLineInfoVector[i].end_x - myapp::mDynamicMapParam->mLineInfoVector[i].begin_x;
                        mirror_width = myapp::mDynamicMapParam->mLineInfoVector[i].begin_x + myapp::mDynamicMapParam->mLineInfoVector[i].end_x;
                    }
                }
            }
            else
            {
                mirror_width = myapp::mDynamicMapParam->m_width;
            }
            if (object_param.GetObjectName().compare("StationView") == ZERO)
                mirror_width = mirror_width + all_name_offset*2;
        } else if (nonmirror_name.contains("interval"))
        {
            mirror_width = myapp::mDynamicMapParam->m_interval_begin_x + myapp::mDynamicMapParam->m_interval_end_x;
        } else
        {
            mirror_width = myapp::mDynamicMapParam->m_width;
        }
        QPoint tmpPos = original_paramobject->GetPos();
        int tmpX = mirror_width - tmpPos.x();
        tmpPos.setX(tmpX);
        object_param.SetPos(tmpPos);
        object_param.SetShowLeft(original_paramobject->GetShowLeft());
        object_param.SetName(original_paramobject->GetObjectName().toLower().left(original_paramobject->GetObjectName().size() - 4) +
                                                    QString::number(object_param.GetStId()));
    } else {
        object_param.SetPos(original_paramobject->GetPos());
        object_param.SetName(original_paramobject->GetObjectName().toLower().left(original_paramobject->GetObjectName().size() - 4));
    }

    if (NULL != mirror_info->object)
    {
        mirror_info->object->setParent(this);
        if (original_paramobject->GetObjectName() == "SingleView")
        {
            CopyOneAttribute("normal", originaldata, mirror_info);
            object_param.SetName(originaldata->object->GetObjectParam()->GetName());
        }
        if (original_paramobject->GetObjectName() == "TimeView")
        {
            CopyOneAttribute("timeformat", originaldata, mirror_info);
            CopyOneAttribute("style", originaldata, mirror_info);
        }
        mirror_info->object->SetObjectParam(object_param);

        connect(mirror_info->object, &ViewObject::sgl_viewobject_select_to_editwidget, this, &EditWidget::slt_find_changed_viewobject);
        connect(mirror_info->object, &ViewObject::sgl_viewobject_update_to_editwidget, this, &EditWidget::slt_update_to_attribute);
        connect(mirror_info->object, &ViewObject::signalSelect, this, &EditWidget::ctrl_select);
        connect(mirror_info->object, &ViewObject::signalDelete, this, &EditWidget::sltDeleteObject);
        connect(mirror_info->object, &ViewObject::signalCopy,   this, &EditWidget::sltCopyObjectData);

        mObjectVector.push_back(mirror_info);

        return mirror_info->object->GetObjectParam()->GetRandom();
    } else {
        delete mirror_info;
        mirror_info = NULL;
    }

    return STR_EMPTY;
}

void EditWidget::ctrl_select(QString id)
{
    foreach (ViewObjectInfo *info, mObjectVector)
    {
        if (ZERO == info->object->GetObjectParam()->GetRandom().compare(id))
        {
            info->object->Select();
            this->setFocus();
        }
    }
}

void EditWidget::slt_find_changed_viewobject(QString id)
{
    for (int i = 0; i < mObjectVector.size(); i++)
    {
        if (ZERO == mObjectVector[i]->object->GetObjectParam()->GetRandom().compare(id))
        {
            mObjectVector[i]->object->Select();
            emit sgl_attribute_to_showwidget(id, mObjectVector[i]);
        }
        else
        {
            mObjectVector[i]->object->Cancel();
        }
    }
}

void EditWidget::slt_update_to_attribute(QString id)
{
    for (int i = 0; i < mObjectVector.size(); i++)
    {
        if (ZERO == mObjectVector[i]->object->GetObjectParam()->GetRandom().compare(id))
        {
            emit sgl_update_to_showwidget(id, mObjectVector[i]);
            break;
        }
    }
}

void EditWidget::slt_list_to_graphics(QString id_current, QString id_previous)
{
    Q_UNUSED(id_previous);
    if (id_current == "")
        return;

    for (int i = 0; i < mObjectVector.size(); i++)
    {
        if (ZERO == mObjectVector[i]->object->GetObjectParam()->GetRandom().compare(id_current))
        {
            mObjectVector[i]->object->Select();
            emit sgl_update_to_showwidget(id_current, mObjectVector[i]);
        }
        else
        {
             mObjectVector[i]->object->Cancel();
        }
    }
}

void EditWidget::CopyData(ViewObjectInfo *ptr_info)
{
    if (NULL == ptr_info)
        return;

    ViewObjectInfo *copy_ptr = new ViewObjectInfo;

    int type = 0;
    for (int i = 0; i < myapp::object_num; i++ )
    {
        if ( ZERO == s_object[i].object_name.compare(ptr_info->object->GetObjectParam()->GetObjectName()))
        {
            type = QMetaType::type(s_object[i].object_register_name.toLatin1());
            if (type == 0)
            {
               return;
            }
            break;
        }
    }

    copy_ptr->object = static_cast<ViewObject*>(QMetaType::metaObjectForType(type)->newInstance());

    copy_ptr->object->SetObjectParam(*ptr_info->object->GetObjectParam());

    copy_ptr->object->GetObjectParam()->SetRandom(myapp::getRandomString());

    mClipboard = copy_ptr;

}

void EditWidget::sltCopyObjectData(QString random)
{
    if (random == "")
        return;

    if (mCopyID == random )
        return;

    mCopyID = random;
}

void EditWidget::sltDeleteObject(QString random)
{
    ViewObjectInfo *del_info = NULL;

    for (int i = 0; i < mObjectVector.size(); i++)
    {
        if (ZERO == mObjectVector[i]->object->GetObjectParam()->GetRandom().compare(random))
        {
            emit signal_delete(random);

            disconnect(mObjectVector[i]->object, &ViewObject::sgl_viewobject_select_to_editwidget, this, &EditWidget::slt_find_changed_viewobject);
            disconnect(mObjectVector[i]->object, &ViewObject::sgl_viewobject_update_to_editwidget, this, &EditWidget::slt_update_to_attribute);
            disconnect(mObjectVector[i]->object, &ViewObject::signalSelect, this, &EditWidget::ctrl_select);
            disconnect(mObjectVector[i]->object, &ViewObject::signalDelete, this, &EditWidget::sltDeleteObject);
            disconnect(mObjectVector[i]->object, &ViewObject::signalCopy,   this, &EditWidget::sltCopyObjectData);

            del_info  = mObjectVector[i];
            break;
        }
    }

    if (del_info)
    {
        mObjectVector.removeOne(del_info);
        delete  del_info->object;
        del_info->object = NULL;
        delete  del_info;
        del_info = NULL;
    }
}

//stationSpacing 单条线路是否镜像：向右：非镜像；向左：镜像；
QMap<QString, QString> EditWidget::GenerateForStationView(QString object_name,
                                                          AutoData *data,
                                                          Staggered staggered,
                                                          int station_num,
                                                          int lineIndex,
                                                          int startStationId,
                                                          int stationSpacing,
                                                          QPoint nameOffset)
{
    QMap<QString, QString> random_name_map;
    if (object_name == "") return random_name_map;

    int type = 0;
    int width = 50;
    int height = 50;
    QPoint pos;

    bool isShowLeft = false;

    for (int loop = 0; loop < station_num; loop++)
    {
         if (object_name == "LineView")
         {
             type = QMetaType::type(s_object[LINEVIEW].object_register_name.toLatin1());
             if (type == 0) return random_name_map;
             //第一条线路的第一个LineView不显示
             if (0 == loop && (1 == lineIndex)) {
                 continue;
             } else {
                 pos = QPoint((data[loop].pos.x() - (stationSpacing / 2)), data[loop].pos.y());
             }
             //LineView控件的宽度可以为0，此时表示根据站点间距自动设置宽度，大于0时，设置的值强制生效
             if (0 == data[loop].line_width) {
//                 width = abs(stationSpacing) - data[loop].point_width;
                 width = abs(stationSpacing);
             } else {
                 width = data[loop].line_width;
             }
             height = data[loop].line_height;
             //站点间距为负数，表示方向为从右向左
             if (stationSpacing < 0) {
                 isShowLeft = true;
             }
         }
         else if (object_name == "PointView")
         {
             type = QMetaType::type(s_object[POINTVIEW].object_register_name.toLatin1());
             if (type == 0) return random_name_map;
             pos = data[loop].pos;
             width = data[loop].point_width;
             height = data[loop].point_height;
         }
         else if (object_name == "StationView")
         {
             type = QMetaType::type(s_object[STATIONVIEW].object_register_name.toLatin1());

             if (type == 0) return random_name_map;
             int y = 0;
             if (staggered == Odd_Up)//奇上
             {
                 if ((loop +1) % 2 == 0)
                     y = data[loop].pos.y() + data[loop].station_height/2 + data[loop].point_height/2 + nameOffset.y();
                 else
                     y = data[loop].pos.y() - data[loop].station_height/2 - data[loop].point_height/2 - nameOffset.y();
             }
             else if (staggered == Even_Up)
             {
                 if ((loop +1) % 2 == 0)
                     y = data[loop].pos.y() - data[loop].station_height/2 - data[loop].point_height/2 - nameOffset.y();
                 else
                     y = data[loop].pos.y() + data[loop].station_height/2 + data[loop].point_height/2 + nameOffset.y();
             }
             else if (staggered == All_Up)
             {
                 y = data[loop].pos.y() - data[loop].station_height/2 - data[loop].point_height/2 - nameOffset.y();
             }
             else if (staggered == All_Down)
             {
                 //height就是当前站名图片的高度， point_height就是点的图片的高度，这个算出来的y坐标就是站名图片中点y坐标
                 y = data[loop].pos.y() + data[loop].station_height/2 + data[loop].point_height/2 + nameOffset.y();
             }
             pos = QPoint(data[loop].pos.x() + nameOffset.x(), y);
             width = data[loop].station_width;
             height = data[loop].station_height;
         }
         else if (object_name == "EtaView")
         {
             type = QMetaType::type(s_object[ETAVIEW].object_register_name.toLatin1());
             if (type == 0) return random_name_map;
             pos = data[loop].pos;
         }

         //先加载图片
         ViewObjectInfo *info = new ViewObjectInfo;
         info->object = static_cast<ViewObject*>(QMetaType::metaObjectForType(type)->newInstance());
         if (NULL == info->object)
         {
             delete  info;
             return random_name_map;
         }
//         info->object->setParent(this);

         ParamObject object_param;
         object_param.SetWidth(width);
         object_param.SetHeight(height);
         object_param.SetObjectName(object_name);

         int stId = startStationId + loop;
         object_param.SetName(object_name.toLower().left(object_name.size() - 4) + QString::number(stId));
         object_param.SetRandom(myapp::getRandomString());
         object_param.SetStId(stId);
         object_param.SetShowLeft(isShowLeft);

         if (object_name == "PointView")
         {
             object_param.SetIndex(2);
             object_param.SetPos(pos);
         }
         else if (object_name == "LineView")
         {
             object_param.SetIndex(1);
             object_param.SetPos(pos);
         }
         else if (object_name == "StationView")
         {
             object_param.SetIndex(1);
             object_param.SetPos(pos);

         } else if (object_name == "EtaView")
         {
             object_param.SetIndex(3);
             object_param.SetPos(pos);
         }

         info->object->SetObjectParam(object_param);

         connect(info->object, &ViewObject::sgl_viewobject_select_to_editwidget, this, &EditWidget::slt_find_changed_viewobject);
         connect(info->object, &ViewObject::sgl_viewobject_update_to_editwidget, this, &EditWidget::slt_update_to_attribute);
         connect(info->object, &ViewObject::signalSelect, this, &EditWidget::ctrl_select);
         connect(info->object, &ViewObject::signalDelete, this, &EditWidget::sltDeleteObject);
         connect(info->object, &ViewObject::signalCopy,   this, &EditWidget::sltCopyObjectData);

         mObjectVector.push_back(info);
         random_name_map[info->object->GetObjectParam()->GetRandom()] = info->object->GetObjectParam()->GetName();
    }
    return random_name_map;
}

QMap<QString, QString> EditWidget::GenerateForStationViewInterval(QString object_name, AutoData *data, Staggered staggered, int station_num, int nameOffset)
{
    QMap<QString, QString>  random_name_map;
    if (object_name == "") return random_name_map;

    int type = 0;
    int width = 100;
    int height = 100;
    QPoint pos;

    //循环一个全线图上的每个站点
    for (int loop = 0; loop < station_num; loop++)
    {
         if (object_name == "LineView")
         {
             //loop=0跳过,因为线少一条
             if (loop != 0)
             {
                 type = QMetaType::type(s_object[LINEVIEW].object_register_name.toLatin1());
                 //给出线的位置,当前点和前面一个点x坐标的中间值，也就是第一根线的中心点位置
                 pos = QPoint((data[loop].pos.x() + data[loop - 1].pos.x())/2, data[loop].pos.y());
                 if (type == 0) return random_name_map;
             }
             else continue;

             //LineView控件的宽度可以为0，此时表示根据站点间距自动设置宽度，大于0时，设置的值强制生效
             if (0 == data[loop].line_width) {
                 width = abs(data[loop].pos.x() - data[loop - 1].pos.x());
             } else {
                 width = data[loop].line_width;
             }
             height = data[loop].line_height;
         }
         else if (object_name == "PointView")
         {
             type = QMetaType::type(s_object[POINTVIEW].object_register_name.toLatin1());
             pos = data[loop].pos;
             if (type == 0) return random_name_map;

             width = data[loop].point_width;
             height = data[loop].point_height;
         }
         else
         {
             type = QMetaType::type(s_object[STATIONVIEW].object_register_name.toLatin1());
             pos = data[loop].pos;
             if (type == 0) return random_name_map;

             width = data[loop].station_width;
             height = data[loop].station_height;
         }

         //先加载图片
         ViewObjectInfo *info = new ViewObjectInfo;
         info->object = static_cast<ViewObject*>(QMetaType::metaObjectForType(type)->newInstance());
         if (NULL == info->object)
         {
             delete  info;
             return random_name_map;
         }

         ParamObject object_param;
         object_param.SetWidth(width);
         object_param.SetHeight(height);
         object_param.SetObjectName(object_name);
         object_param.SetName(object_name.toLower().left(object_name.size() - 4) + QString::number(loop + 1));
         object_param.SetRandom(myapp::getRandomString());
         object_param.SetStId(loop + 1);

         if (object_name == "PointView")
         {
             object_param.SetIndex(2);
             object_param.SetPos(pos);
             //object_param.SetPos(pos + QPoint(0, -25));  //此处点不在中间有白底，y坐标向下移动25个偏移量
         }
         else if (object_name == "LineView")
         {
             object_param.SetIndex(1);
             object_param.SetPos(pos);
         }
         else if (object_name == "StationView")
         {
             object_param.SetIndex(2);

             int x = 0, y = 0;
             x = pos.x();
             if (staggered == Odd_Up)//奇上
             {
                 if ((loop +1) % 2 == 0)
                     y = pos.y() + data[loop].station_height/2 + data[loop].point_height/2 + nameOffset;
                 else
                     y = pos.y() - data[loop].station_height/2 - data[loop].point_height/2 - nameOffset;
             }
             else if (staggered == Even_Up)
             {
                 if ((loop +1) % 2 == 0)
                     y = pos.y() - data[loop].station_height/2 - data[loop].point_height/2 - nameOffset;
                 else
                     y = pos.y() + data[loop].station_height/2 + data[loop].point_height/2 + nameOffset;
             }
             else if (staggered == All_Up)
             {
                 y = pos.y() - data[loop].station_height/2 - data[loop].point_height/2 - nameOffset;
             }
             else if (staggered == All_Down)
             {
                 //height就是当前站名图片的高度， point_height就是点的图片的高度，这个算出来的y坐标就是站名图片中点y坐标
                 y = pos.y() + data[loop].station_height/2 + data[loop].point_height/2 + nameOffset;
             }
             object_param.SetPos(QPoint(x, y));
             //object_param.SetPos(QPoint(x, y) + QPoint(0, -160));//此处计算偏移量，有白底
         }

         info->object->SetObjectParam(object_param);

         connect(info->object, &ViewObject::sgl_viewobject_select_to_editwidget, this, &EditWidget::slt_find_changed_viewobject);
         connect(info->object, &ViewObject::sgl_viewobject_update_to_editwidget, this, &EditWidget::slt_update_to_attribute);
         connect(info->object, &ViewObject::signalSelect, this, &EditWidget::ctrl_select);
         connect(info->object, &ViewObject::signalDelete, this, &EditWidget::sltDeleteObject);
         connect(info->object, &ViewObject::signalCopy,   this, &EditWidget::sltCopyObjectData);

         mObjectVector.push_back(info);
         random_name_map[info->object->GetObjectParam()->GetRandom()] = info->object->GetObjectParam()->GetName();
    }
    return random_name_map;
}

QString EditWidget::AutoGenerate(QString object_name, QString &struct_show_item_name, QPoint pos, int w, int h)
{
    if (object_name == "") return STR_EMPTY;

    int width = w;
    int height = h;
    int res = 0;
    for (int i = 0; i < myapp::object_num; i++ )
    {
        if (ZERO == s_object[i].object_name.compare(object_name))
        {
            res = QMetaType::type(s_object[i].object_register_name.toLatin1());
            break;
        }
    }

    if (res == 0) return STR_EMPTY;

    ParamObject object_param;
    object_param.SetObjectName(object_name);
    object_param.SetName(object_name.toLower().left(object_name.size() - 4));
    object_param.SetPos(pos);
    object_param.SetIndex(1);

    if (ZERO == object_name.compare("SingleView"))
    {
        object_param.SetIndex(-1);
        m_max_single_num ++;
        object_param.SetName(struct_show_item_name + QString::number(m_max_single_num));
        struct_show_item_name = object_param.GetName();
    }

    if (ZERO == object_name.compare("TrainView"))
    {
        object_param.SetIndex(1);
    }

    if (ZERO == object_name.compare("TrainposView"))
    {
        object_param.SetIndex(2);
    }

    //门有可能是显示全图，所以最后显示
    if (ZERO == object_name.compare("DoorView"))
    {
        object_param.SetIndex(5);
    }
    object_param.SetWidth(width);
    object_param.SetHeight(height);
    object_param.SetStId(0);//stationview中的别的控件，只关心currid，不关心stid，比如到达站显示
    object_param.SetRandom(myapp::getRandomString());

    ViewObjectInfo *info = new ViewObjectInfo;

    info->object = static_cast<ViewObject*>(QMetaType::metaObjectForType(res)->newInstance());

    if (NULL != info->object)
    {
        info->object->SetObjectParam(object_param);

        connect(info->object, &ViewObject::sgl_viewobject_select_to_editwidget, this, &EditWidget::slt_find_changed_viewobject);
        connect(info->object, &ViewObject::sgl_viewobject_update_to_editwidget, this, &EditWidget::slt_update_to_attribute);
        connect(info->object, &ViewObject::signalSelect, this, &EditWidget::ctrl_select);
        connect(info->object, &ViewObject::signalDelete, this, &EditWidget::sltDeleteObject);
        //connect(info->object, &ViewObject::signalCopy,   this, &EditWidget::sltCopyObjectData);

        mObjectVector.push_back(info);

        return info->object->GetObjectParam()->GetRandom();
    }

    return  STR_EMPTY;
}

void EditWidget::xml_to_vector(QString xml_path, QString file_name, StructureWidget *struture_widget)
{
    QString fullpath = xml_path + file_name;

    QFile file(fullpath);
    if (!file.open(QFile::ReadOnly))
    {
        LOG_QDEBUG << "no file, file name:" << fullpath;
        return;
    }
    QDomDocument doc;
    QString err_msg;
    int err_line;
    int err_column;
    if (!doc.setContent(&file, false, &err_msg, &err_line, &err_column))
    {
        file.close();
        LOG_QDEBUG << "XML setContent fail,Msg:" << err_msg << " Line:" << err_line << " Column:" << err_column;
        return;
    }

    if (doc.isNull())
    {
        file.close();
        LOG_QDEBUG << "doc is null";
        return;
    }
    QDomElement body = doc.documentElement();

    if (body.hasAttribute("current"))
    {
        myapp::mDynamicMapParam->m_interval_cur_station_pos = body.attribute("current","0").toInt();
    }
    if (body.hasAttribute("total"))
    {
        myapp::mDynamicMapParam->m_interval_station_num = body.attribute("total", 0).toInt();
    }

    if (body.hasAttribute("width"))
    {
        setFixedWidth(body.attribute("width", 0).toInt());
    }

    if (body.hasAttribute("height"))
    {
        setFixedHeight(body.attribute("height", 0).toInt());
    }

    QDomElement ui = body.firstChildElement("ui");

    QDomNodeList itemList = ui.childNodes();

    if (itemList.isEmpty())
    {
        LOG_QDEBUG << "no items";
        file.close();
        return;
    }

    for (int i = 0; i < itemList.count(); i++)
    {
        QDomElement item;
        item = itemList.item(i).toElement();
        if (item.isComment()||item.isNull())
        {
            continue;
        }

        QString object_name = item.attribute("type", "null");
        QString name = item.attribute("name", "null");
        QString stid = item.attribute("stid", "0");

        int ret = 0;
        for (int i = 0; i < myapp::object_num; i++ )
        {
            if ( ZERO == s_object[i].object_name.compare(object_name))
            {
                ret = QMetaType::type(s_object[i].object_register_name.toLatin1());
                break;
            }
        }

        if (ret == 0)
            return;

        ViewObjectInfo *info = new ViewObjectInfo;

        info->object = static_cast<ViewObject*>(QMetaType::metaObjectForType(ret)->newInstance());

        if (NULL != info->object)
        {
            mObjectVector.push_back(info);
            info->object->ParseXML(&item);
            info->object->GetObjectParam()->SetObjectName(object_name);
            if (object_name == "SingleView")
            {
                QString name = info->object->GetObjectParam()->GetName();
                if (name.size() > 6) //single
                {
                    int num = name.right(name.size()-6).toInt();
                    if (num != 0)
                    {
                        if (num > m_max_single_num)
                            m_max_single_num = num;
                    }
                }
            }
            connect(info->object, &ViewObject::sgl_viewobject_select_to_editwidget, this, &EditWidget::slt_find_changed_viewobject);
            connect(info->object, &ViewObject::sgl_viewobject_update_to_editwidget, this, &EditWidget::slt_update_to_attribute);
            connect(info->object, &ViewObject::signalSelect, this, &EditWidget::ctrl_select);
            connect(info->object, &ViewObject::signalDelete, this, &EditWidget::sltDeleteObject);
            connect(info->object, &ViewObject::signalCopy,   this, &EditWidget::sltCopyObjectData);
            info->object->GetObjectParam()->SetRandom(myapp::getRandomString());
            struture_widget->AddData(file_name, info->object->GetObjectParam()->GetRandom(), name, stid.toInt());
        }
        else
        {
            delete info;
        }
    }
    file.close();
}

void EditWidget::setPath(QString path)
{
    mPath = path;
}

void EditWidget::savecfg()
{
    QString file_name = QString("%1/xml/%2").arg(mPath).arg(mFileName);

    QFile file(file_name);

    if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate)) return;
    QDomDocument doc;
    QDomProcessingInstruction instruction;
    instruction = doc.createProcessingInstruction("xml", "version=\"1.0\" encoding=\"UTF-8\"");

    doc.appendChild(instruction);
//    // 添加根元素
    QDomElement root = doc.createElement("body");

    root.setAttribute("scale", "1.0");
    root.setAttribute("height", QString::number(myapp::mDynamicMapParam->m_height));
    root.setAttribute("width", QString::number(myapp::mDynamicMapParam->m_width));

    //for value offset
    if (mFileName.contains(AllFlag))
        root.setAttribute("all_offset", QString::number(myapp::mDynamicMapParam->m_unequal_spacing_offset));

    if (mFileName.contains(IntervalFlag))
    {
        root.setAttribute("interval_offset", QString::number(myapp::mDynamicMapParam->m_interval_unequal_spacing_offset));
        root.setAttribute("current", QString::number(myapp::mDynamicMapParam->m_interval_cur_station_pos));
        root.setAttribute("interval_station_num", QString::number(myapp::mDynamicMapParam->m_interval_station_num));
        root.setAttribute("all_station_num", QString::number(myapp::mDynamicMapParam->m_station_total));
    }

    QDomElement dom = doc.createElement("ui");
    for (int loop = 0; loop < mObjectVector.size(); loop++)
    {
        QDomElement dom_it;
        mObjectVector[loop]->object->PacketXML(&dom_it);
        dom.appendChild(dom_it);
    }

    root.appendChild(dom);
    doc.appendChild(root);

    QTextStream out(&file);

    // 将文档保存到文件，4为子元素缩进字符数
    doc.save(out, 4);
    file.close();
}
